package com.aabte.permissionframeworklearn.permission.service;

import com.aabte.permissionframeworklearn.permission.common.RequestHolder;
import com.aabte.permissionframeworklearn.permission.exception.ParamException;
import com.aabte.permissionframeworklearn.permission.mapper.SysAclMapper;
import com.aabte.permissionframeworklearn.permission.mapper.SysAclModuleMapper;
import com.aabte.permissionframeworklearn.permission.model.SysAclModule;
import com.aabte.permissionframeworklearn.permission.param.AclModuleParam;
import com.aabte.permissionframeworklearn.permission.util.BeanValidator;
import com.aabte.permissionframeworklearn.permission.util.IpUtil;
import com.aabte.permissionframeworklearn.permission.util.LevelUtil;
import com.google.common.base.Preconditions;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author Daniel
 */
@Service
public class SysAclModuleService {

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysLogService sysLogService;

    public SysAclModule save(AclModuleParam param) {

        BeanValidator.check(param);
        if (checkExist(param.getParentId(), param.getName(), param.getId())) {
            throw new ParamException("同一层级下存在相同名称的权限模块！");
        }

        SysAclModule sysAclModule = SysAclModule.builder()
                .name(param.getName())
                .parentId(param.getParentId())
                .remark(param.getRemark())
                .seq(param.getSeq())
                .status(param.getStatus())
                .operator(RequestHolder.getCurrentUser().getUsername())
                .operateTime(new Date())
                .operateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()))
                .level(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()))
                .build();

        sysAclModuleMapper.insertSelective(sysAclModule);
        sysLogService.saveAclModuleLog(null, sysAclModule);
        return sysAclModule;
    }


    public SysAclModule update(AclModuleParam param) {

        BeanValidator.check(param);
        if (checkExist(param.getParentId(), param.getName(), param.getId())) {
            throw new ParamException("同一层级下存在相同名称的权限模块！");
        }

        SysAclModule before = sysAclModuleMapper.selectByPrimaryKey(param.getId());
        Preconditions.checkNotNull(before, "待更新的权限模块不存在！");

        SysAclModule after = SysAclModule.builder()
                .id(param.getId())
                .name(param.getName())
                .parentId(param.getParentId())
                .remark(param.getRemark())
                .seq(param.getSeq())
                .status(param.getStatus())
                .operator(RequestHolder.getCurrentUser().getUsername())
                .operateTime(new Date())
                .operateIp(IpUtil.getRemoteIpAddress(RequestHolder.getCurrentRequest()))
                .level(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()))
                .build();

        updateWidthChild(before, after);
        sysLogService.saveAclModuleLog(before, after);
        return after;
    }

    @Transactional(rollbackFor = Exception.class)
    void updateWidthChild(SysAclModule before, SysAclModule after) {
        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();

        if (!after.getLevel().equals(before.getLevel())) {
            List<SysAclModule> childAclModules = sysAclModuleMapper.getChildAclModuleListByLevel(before.getLevel());
            if (CollectionUtils.isNotEmpty(childAclModules)) {
                for (SysAclModule childAclModule : childAclModules) {
                    String level = childAclModule.getLevel();
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        childAclModule.setLevel(level);
                    }
                }
                sysAclModuleMapper.batchUpdateLevel(childAclModules);
            }
        }
        sysAclModuleMapper.updateByPrimaryKeySelective(after);
    }

    private boolean checkExist(Long parentId, String aclModuleName, Long id) {
        return sysAclModuleMapper.countByNameAndParentId(aclModuleName, parentId, id) > 0;
    }

    private String getLevel(Long aclModuleId) {
        SysAclModule sysAclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        if (null == sysAclModule) {
            return null;
        }
        return sysAclModule.getLevel();
    }

    public SysAclModule delete(Long id) {

        SysAclModule sysAclModule = sysAclModuleMapper.selectByPrimaryKey(id);
        Preconditions.checkNotNull(sysAclModule, "待删除的权根模块不存在！");

        boolean isExistChild = sysAclModuleMapper.countByParentId(id) > 0;
        if (isExistChild) {
            throw new ParamException("当前权根模块下有子模块，无法删除！");
        }

        boolean isExistAcls = sysAclMapper.countByAclModuleId(id) > 0;
        if (isExistAcls) {
            throw new ParamException("当前权根模块下有权限点，无法删除！");
        }

        sysAclModuleMapper.deleteByPrimaryKey(id);
        return sysAclModule;
    }
}
